#!/usr/bin/env python3
import logging
import json
import os
import signal
import sys
import urllib
import urllib.request
# import urlparse

from multiprocessing import Process

import oauth2
from oauth2 import Provider
from oauth2.error import UserNotAuthenticated
from oauth2.grant import AuthorizationCodeGrant
from oauth2.tokengenerator import Uuid4
from oauth2.store.memory import ClientStore, TokenStore
from oauth2.web import AuthorizationCodeGrantSiteAdapter

from oauth2.web.tornado import OAuth2Handler
from tornado.ioloop import IOLoop
from tornado.web import Application, url

logging.basicConfig(level=logging.DEBUG)

class TestSiteAdapter(AuthorizationCodeGrantSiteAdapter):
    """
    This adapter renders a confirmation page to the user can confirm the auth request.
    """

    CONFIRMATION_TEMPLATE = """
    <!DOCTYPE html>
    <html>
        <body>
            <p><a href="{url}&confirm=1">confirm</a></p>
            <p><a href="{url}&confirm=0">deny</a></p>            
        </body>
    </html>
    """
    
    def render_auth_page(self, request, response, environ, scopes, client):
        url = request.path + "?" + request.query_string
        response.body = self.CONFIRMATION_TEMPLATE.format(url=url)

        return response

    def authenticate(self, request, environ, scopes, client):
        if request.method == "GET":
            if request.get_param("confirm") == "1":
                return
        raise UserNotAuthenticated

    def user_has_denied_access(self, request):
        if request.method == "GET":
            if request.get_param("confim") == "0":
                return True

        return False

def get_host_ip(ifname):
    import socket
    import fcntl
    import struct

    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    info_b = fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s', ifname[:15].encode("UTF8")))
    return socket.inet_ntoa(info_b[20:24])                                                                                        


def run_auth_server():
    host_ip = get_host_ip("eth0")
    redirect_callback = "http://%s:8081/callback" %(host_ip)

    client_store = ClientStore()
    client_store.add_client(client_id="car", client_secret="xyz",\
                    redirect_uris=[redirect_callback])

    token_store = TokenStore()

    provider = Provider(access_token_store=token_store,
                    auth_code_store=token_store,
                    client_store=client_store,
                    token_generator=Uuid4())
    provider.add_grant(AuthorizationCodeGrant(site_adapter=TestSiteAdapter()))

    try:
        app = Application([
                url(provider.authorize_path, OAuth2Handler, dict(provider=provider)),
                url(provider.token_path, OAuth2Handler, dict(provider=provider)),
            ])

        app.listen(8080)
        print("Starting OAuth2 server on :localhost8080/...")
        IOLoop.current().start()

    except KeyboardInterrupt:
        IOLoop.close()

def main():
    auth_server = Process(target=run_auth_server)
    auth_server.start()

    def sigint_handler(signal, frame):
        print("Terminating Servers...")
        auth_server.terminate()
        auth_server.join()
        app_server.terminate()
        app_server.join()

    signal.signal(signal.SIGINT, sigint_handler)

if __name__ == '__main__':
    main()
